package com.spzx.product.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.spzx.product.domain.Product;
import com.spzx.product.domain.ProductDetails;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.mapper.ProductMapper;
import com.spzx.product.mapper.ProductSkuMapper;
import com.spzx.product.service.IProductDetailsService;
import com.spzx.product.service.IProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.service.IProductSkuService;
import com.spzx.product.service.ISkuStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-12-20
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    @Autowired
    private IProductSkuService skuService;
    @Autowired
    private ProductSkuMapper skuMapper;
    @Autowired
    private ISkuStockService stockService;
    @Autowired
    private IProductDetailsService detailsService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<Product> selectProductList() {
        return baseMapper.selectProductList();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertProduct(Product product) {
        // 1.添加商品表中的内容
        // 这里我们完成product的插入之后，就会自动给product安排一个id，所以下面要调用product.getId()是没有问题的
        baseMapper.insert(product);
        List<ProductSku> productSkuList = product.getProductSkuList();
        // 获取product对象中的productSkuList，但是这List当中的ProductSku对象字段不完整
        // 我们需要手动组装完整对象，并且将数据插入到数据库当中
        // 遍历productSkuList
        // 2.添加商品sku表中的内容
        for (int i = 0; i < productSkuList.size(); i++) {
            // 获取到的productSku不完整，手动组装完整对象
            ProductSku productSku = productSkuList.get(i);
            productSku.setStatus(0);
            productSku.setProductId(product.getId());
            productSku.setSkuCode(product.getId() + "_" + i);
            String skuName = product.getName() + " " + productSku.getSkuSpec();
            productSku.setSkuName(skuName);
            // 将productSku保存到数据库中，同样的，此时productSku的id是自动生成的
            skuService.save(productSku);

            // 3.添加商品库存表中的内容
            SkuStock stock = new SkuStock();
            stock.setSkuId(productSku.getId());
            stock.setTotalNum(productSku.getStockNum());
            stock.setLockNum(0);
            stock.setAvailableNum(productSku.getStockNum());
            stock.setSaleNum(0);
            stock.setStatus(0);
            stockService.save(stock);
        }
        // 4.添加商品详情表中的内容
        ProductDetails details = new ProductDetails();
        details.setProductId(product.getId());
        String detailString = String.join(",", product.getDetailsImageUrlList());
        details.setImageUrls(detailString);
        detailsService.save(details);

        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Long id, Integer status) {
        //更新指定id的商品的状态
        LambdaUpdateWrapper<Product> updateProduct = new LambdaUpdateWrapper<>();
        updateProduct.eq(Product::getId,id)
                .set(Product::getStatus,status);
        baseMapper.update(null,updateProduct);
        //更新商品sku的状态
        LambdaUpdateWrapper<ProductSku> updateProductSku = new LambdaUpdateWrapper<>();
        updateProductSku.eq(ProductSku::getProductId,id)
                .set(ProductSku::getStatus,status);
        skuService.update(null,updateProductSku);
        //若我们更新了商品的状态为上架，那么我们就要去将redis中专门用来存储sku_id的Bitmap中
        //将对应偏移量为sku_id的值修正为true，反之则修改为false
        String bitKey = "product:sku:data";
        List<ProductSku> productSkuList = skuMapper.selectList(new LambdaQueryWrapper<ProductSku>()
                .eq(ProductSku::getProductId, id));
        //商品状态改为上架，那么就将对应商品id的所有sku规格对象的skuId从Bitmap中设置为true
        if (status == 1){
            productSkuList.forEach(sku -> {
                redisTemplate.opsForValue().setBit(bitKey,sku.getId(),true);
            });
        } else {
            //商品状态改为下架，那么就将对应商品id的所有sku规格对象的skuId从Bitmap中设置为false
            productSkuList.forEach(sku -> {
                redisTemplate.opsForValue().setBit(bitKey,sku.getId(),false);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeProduct(List<Long> ids) {
        //1.删除商品表中的数据
        baseMapper.deleteBatchIds(ids);
        //2.删除sku表中的数据
        LambdaQueryWrapper<ProductSku> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProductSku::getProductId,ids)
                .select(ProductSku::getId);
        //获取所有商品id在ids集合中的商品sku集合，并且因为select(ProductSku::getId)的缘故
        //获取到的对象是一个只有id属性的ProductSku对象集合
        List<ProductSku> productSkus = skuService.getBaseMapper().selectList(queryWrapper);
        //通过stream流，将刚刚所有的ProductSku对象转换成skuId集合
        List<Long> skuIds = productSkus.stream().map((productSku) -> {
            return productSku.getId();
        }).toList();
        //准备删除sku表的数据
        skuService.remove(new LambdaQueryWrapper<ProductSku>()
                .in(ProductSku::getId,skuIds));
        //3.删除商品详情表中的数据
        detailsService.remove(new LambdaQueryWrapper<ProductDetails>()
                .in(ProductDetails::getProductId,ids));
        //4.删除sku库存表的数据
        stockService.remove(new LambdaQueryWrapper<SkuStock>()
                .in(SkuStock::getSkuId,skuIds));
        return 1;
    }

}
